Technical Note TN2074
HIView APIs vs. Control Manager APIs

目次

Mac OS X 10.2(Jaguar)から、すべてのユーザインタフェース要素(メニュー、ウインドウ、コントロールなど)を処理する新しい API のセットが導入されました。これらの API は C 言語ベースですが、その精神はオブジェクト指向で、すべての「クラス」は基本クラスとなる HIObject.HIView に由来します。HIObject.HIView は、これまで Control Manager が提供してきたすべての機能に加えて、それ以上の機能を提供するクラスです。

プログラミングの観点からいうと、HIViews はコントロールであり、コントロールは HIViews です。つまり、HIViews に対してすべての Control Manager API を使用でき、コントロールに対しては HIView API を使用できます。コンパイラは、HIViewRefs と ControlRefs を同じように受け入れます。

このテクニカルノートでは、類似する API と動作について説明します。新しい HIToolbox モデルに基づいてプログラムのユーザインタフェースを開発したいデベロッパの方々を対象とします。一部の動作はインタフェースを所有するウインドウのコンポジティング属性に依存するため、その場合には、そのことを明示します。

比較の内容はすべて、Mac OS X 10.2 以降でのみ有効です。

[2003 年 10 月 29 日]



類似 API

先頭に戻る



GetRootControl、CreateRootControl vs. HIViewGetRoot

ウィンドウの kWindowCompositingAttribute が設定されているかどうかに関係なく、HIViewGetRoot は必ずウインドウの Root View を返します。Root View は、ウインドウの全体構造を表し、標準のウインドウウィジェット(閉じる、最小化、ズームの各ボタン、およびサイズ変更コントロールなど)がすべて揃っています。

ウィンドウの kWindowCompositingAttribute が設定されている場合、CreateRootControlerrRootAlreadyExists エラーを返し、GetRootControl は実際にウインドウの Content View を返します。Content View は、HIViewFindByID 使用しても取得することができます。



リスト 1. Content View の取得

GetRootControl(theWindow, &theContentView);

// または

HIViewFindByID(HIViewGetRoot(theWindow),
kHIViewWindowContentID,
&theContentView);



ウィンドウの kWindowCompositingAttribute が設定されていない場合、GetRootControl は、ウインドウの Content View の子である Root Control(前述の Root View と混同しないこと)を返します。ただし、これは事前に CreateRootControl を直接または間接的に CreateFooControl API を呼び出した場合に限ります。呼び出していない場合、GetRootControlerrNoRootControl エラーを返します。

先頭に戻る



EmbedControl vs. HIViewAddSubview

パラメータの親子関係が逆になっているという事実に加え、これらの API は相互に互換性がありません。HIViewAddSubview は、コンテナコントロールまたは(通常は、HIView 作成 API のウインドウパラメータに NULL を渡して)ウインドウの外部で作成した HIView を対象に使用することができます。これに対して、EmbedControl は、コンテナコントロールがすでにウインドウ(コンポジティングまたは非コンポジティング)に埋め込まれている場合にのみ成功します。コンテナコントロールがウインドウに埋め込まれていない場合、EmbedControlerrInvalidWindowRef エラーを返します。コンポジティングモデルと HIView モデルは相補的に設計されたため、EmbedControl は非コンポジティングウインドウでのみ、HIViewAddSubview はコンポジティングウインドウでのみ使用することをお勧めします。

先頭に戻る



GetSuperControl vs. HIViewGetSuperview

パラメータと戻り値が異なる方法で設定されるという事実を除けば、この 2 つの API の間に考え方の違いはありません。対象がコンポジティングウインドウの場合、これらの API は必ず同じ親を返します。非コンポジティングウインドウの場合、このルールの唯一の例外として、ルートコントロールの親を要求します。つまり、GetSuperControlNULL の親と paramErr エラーを返すのに対し、HIViewGetSuperview はその親が Root View であるビューを返します。

先頭に戻る



ShowControl、HideControl vs. HIViewSetVisible

非コンポジティングウインドウでは、3 つの API すべてが即座に描画を開始します。コンポジティングウインドウでは、3 つの API すべてがコントロール/ビュー領域を無効にします。

先頭に戻る



SetControlVisibility vs. HIViewSetVisible

コンポジティングウインドウでは、どちらの API も、SetControlVisibility の最後のパラメータ (Boolean inDoDraw ) の値に関係なく、コントロール/ビュー領域を無効にします。非コンポジティングウインドウでは、HIViewSetVisible は即座に描画を開始し、SetControlVisibility も同様です。ただし、最後のパラメータ (Boolean inDoDraw ) が false に設定されている場合は除きます。

先頭に戻る



IsControlVisible vs. HIViewIsVisible

この 2 つの API はまったく同じです。

先頭に戻る



GetControlBounds vs. HIViewGetBounds

GetControlBounds が QuickDraw の Rect を返し、HIViewGetBoundsHIRect(つまり Core Graphics の CGRect)を返すという事実のほかに、これらの API の動作はウインドウのコンポジティング属性によって決まります。非コンポジティングウインドウの場合は、どちらの API もウインドウの座標系を基準に動作します。しかし、コンポジティングウインドウの場合、GetControlBounds はビューの親の座標系を基準に動作し、HIViewGetBounds はビューの座標系を基準に動作します(したがって、HIView の原点を HIViewSetBoundsOrigin で変更しないかぎり(ほとんどのデベロッパはそうする必要がありません)、HIRect の原点は必ず 0,0 になります)。

先頭に戻る



GetControlBounds vs. HIViewGetFrame

GetControlBounds が QuickDraw の Rect パラメータを返し、HIViewGetBoundsHIRect パラメータ(つまり Core Graphics の CGRect)を返すという事実のほかに、これらの API の動作はウインドウのコンポジティング属性によって決まります。非コンポジティングウインドウの場合は、どちらの API もウインドウの座標系を基準に動作します。しかし、コンポジティングウインドウの場合は、どちらもビューの親の座標系を基準に動作します。

ビューの親がウインドウの Content View である場合、GetControlBoundsHIViewGetFrame は、フォーマットの違いはありますが、同じ矩形を返します。

先頭に戻る



SetControlBounds vs. HIViewSetFrame

SetControlBounds は QuickDraw の Rect パラメータを受け取り、HIViewSetFrameHIRect パラメータ(つまり Core Graphics の CGRect)を受け取るという事実のほかに、これらの API の動作はウインドウのコンポジティング属性によって決まります。非コンポジティングウインドウの場合は、どちらの API もウインドウの座標系を基準に動作します。しかし、コンポジティングウインドウの場合は、どちらもビューの親の座標系を基準に動作します。

ビューの親がウインドウの Content View である場合、SetControlBoundsHIViewSetFrame は、フォーマットの違いはありますが、同じ矩形のビュー/コントロールを設定します。

先頭に戻る



MoveControl/SizeControl vs. HIViewSetFrame

MoveControlSizeControlSInt16 パラメータ(QuickDraw 座標)を受け取り、HIViewSetFrameHIRect パラメータ(つまり Core Graphics の CGRect)を受け取るという事実のほかに、これらの API の動作はウインドウのコンポジティング属性によって決まります。非コンポジティングウインドウの場合は、どちらの API もウインドウの座標系を基準に動作します。しかし、コンポジティングウインドウの場合は、どちらもビューの親の座標系を基準に動作します。

ビューの親がウインドウの Content View である場合、MoveControlHIViewSetFrame は、フォーマットの違いはありますが、ビュー/コントロールを同じポイントに配置します。

先頭に戻る



MoveControl vs. HIViewPlaceInSuperviewAt

MoveControlSInt16 パラメータ(QuickDraw 座標)を受け取り、HIViewPlaceInSuperviewAtfloat パラメータ(Core Graphics 座標)を受け取るという事実のほかに、これらの API の動作はウインドウのコンポジティング属性によって決まります。非コンポジティングウインドウの場合は、どちらの API もウインドウの座標系を基準に動作します。しかし、コンポジティングウインドウの場合は、どちらもビューの親の座標系を基準に動作します。

ビューの親がウインドウの Content View である場合、MoveControlHIViewPlaceInSuperviewAt は、フォーマットの違いはありますが、ビュー/コントロールを同じポイントに配置します。

先頭に戻る



FindControl、FindControlUnderMouse vs. HIViewGetViewForMouseEvent

ウインドウの StandardHandler(CreateNewWindowWindowAttributes パラメータに kWindowStandardHandlerAttribute を追加)にマウスイベントを処理させる方が、他の手段を使うよりもはるかに簡単であり、強くお勧めします。しかし、別の手段を使う必要があるということであれば、HIViewGetViewForMouseEvent によって、親ビューでサブビューのクリックを捉えることができます。FindControlFindControlUnderMouse で、SetControlSupervisor を使う、類似したメカニズムもありますが、完全に正しい動作を実装するには非常に複雑な作業が必要となるのでお勧めしません。これらの点と、この 3 つの API のパラメータと戻り値の設定方法が事実のほかに、FindControlFindControlUnderMouse はウインドウレベルを起点とするのに対し、HIViewGetViewForMouseEvent は HIView 階層の任意のレベルを起点にできることも留意に値します。

先頭に戻る



TestControl vs. HIViewGetPartHit

パラメータと戻り値の設定方法が異なる事実を除けば、これらの API はよく似ています。

先頭に戻る



TrackControl、HandleControlClick vs. HIViewClick

TrackControlHandleControlClick は同じようなアプローチでクリックを処理します。クリックを、モディファイア付き、またはモディファイアなしで、コントロールアクションコールバック付き、またはなしのコントロールの実装コードに渡し、処理の基準となる ControlPartCode を呼び出し元のコードに返します。これに対し、HIViewClick はイベント全体を HIView に渡し、処理を完全に任せます。コールバックはありません。なぜなら、標準と異なる(あるいは補う)動作が必要な場合は、適切なメッセージ (kEventControlTrack ) をオーバーライドするだけでそれを実現できるようにして、マウスボタンが解放されたときの状態(有効な領域またはそうでない領域か)に応じて処理を行う必要がある場合も、適切なメッセージ (kEventControlHit ) をオーバーライドするだけ可能なようにするためです。ControlActionUPPTrackControl または HandleControlClick に渡すことでコールバックを使用していて、HIViewClick を使いたいけれども、(上述のオーバーライドによる方法の代わりに)このコールバックコード維持したい場合は、この ControlActionUPPSetControlAction を使ってコントロールに関連付けることができます。

先頭に戻る



GetBestControlRect vs. HIViewGetSizeConstraints

最良(または最適)な範囲は、コントロール/ビューがサポートできる最小または最大の範囲と異なることがあり、コンテナがサイズ調整を処理するためにこの情報を必要とする場合に備えて、これらの API は相補的に機能します。

先頭に戻る



SetKeyboardFocus vs. HIViewSetFirstSubViewFocus、HIViewSetNextFocus

SetKeyboardFocus は能動的ですが、HIViewSetFirstSubViewFocusHIViewSetNextFocus は受動的です。SetKeyboardFocus を呼び出すと、指定したコントロールにすぐフォーカスが設定されます。それに対し、HIViewSetFirstSubViewFocus を呼び出すと、指定した親ビューにフォーカスが移った時点で指定したサブビューにフォーカスが設定されるように要求するにとどまります。HIViewSetNextFocus を呼び出すと、指定したビューからフォーカスが失われたときに、指定した次のビューにフォーカスが設定されるように要求するにとどまります。

先頭に戻る



AdvanceKeyboardFocus、ReverseKeyboardFocus vs. HIViewAdvanceFocus

まず、AdvanceKeyboardFocusReverseKeyboardFocus は、ウインドウレベルで次にフォーカス可能な要素を探します。これに対して、HIViewAdvanceFocus は、指定したビュー階層で次にフォーカス可能な要素を探します(ウインドウの Root View または Content View を指定すれば、ウインドウレベルでも可能です)。次にフォーカス可能な要素は、特別なフォーカス要求(CODE>HIViewSetFirstSubViewFocus や HIViewSetNextFocus)がないかぎり、どちらの場合もグラフィック位置と階層レベルによって決まります。第二に、HIViewAdvanceFocus は、EventModifiers パラメータに応じて前進も後退も可能です。

第三に、AdvanceKeyboardFocusReverseKeyboardFocus は、コンポジティングウインドウでは機能しないため、代わりに HIViewAdvanceFocus を使用する必要があります。HIViewAdvanceFocusEventModifiers パラメーターの状態に基づいてコントロールグループ間をタブ移動できるように、将来、機能が強化される可能性があります。

先頭に戻る



GetControlByID vs. HIViewFindByID

GetControlByID はウインドウレベルで検索を開始するのに対し、HIViewFindByID は階層レベルで検索を開始するという事実を除けば、これらの API は似ています。ウインドウの Root View または Content View を起点に HIViewFindByID を呼び出すと、GetControlByID の呼び出しと同じ結果が得られます。

先頭に戻る



GetControlFeatures vs. HIViewGetAttributes

GetControlFeatures はコントロール/ビューの機能(kControlSupportsEmbeddingkControlSupportsFocus など)を返しますが、HIViewGetAttributes はコントロール/ビューの属性(Mac OS X 10.2 で唯一定義されている属性である kHIViewSendCommandToUserFocus など)を返します。したがって、一般に、Content View を対象に GetControlFeatures を呼び出すと 0x20042 が返され(embedding、idle、getregion をサポート)、HIViewGetAttributes を呼び出すと 0x0 が返されます。将来リリースされるシステムでは、より多くの属性が定義されるでしょう。



注意:
Mac OS X 10.3 では、新しい API として HIViewGetFeatures が導入されました。この API は、HIViews にとってほとんど有用でないものを除き、GetControlFeatures と同じ機能を返します。有用な機能は名称が変更されています(つまり、kControlSupportsEmbedding の代わりに kHIViewAllowsSubviews)。



先頭に戻る



類似動作

先頭に戻る



DisposeControl vs. CFRelease

すべての HIView は CF ベースの HIObject クラスから派生したものであるため、HIView を対象に CFRetainCFRelease などの API が使用できるようになりました。つまり、CFRelease または DisposeControl を使って任意の HIView を解放することができます。DisposeControl を使い続ける方が読みやすいかもしれません。ちなみに、コントロール/HIView も HIObject なので、DisposeWindow または CFRelease を使ってウインドウを破棄すると解放されるため、たいていの場合は、CFRelease または DisposeControl を自分で呼び出す必要はありません。

先頭に戻る



CreateCustomControl vs. HIObjectCreate

カスタムコントロールを作成する場合には、HIView モデルを採用することを強くお勧めします。その方が簡単で、今後進む方向だからです。

先頭に戻る



SetControlSupervisor vs. kEventControlInterceptSubviewClick

これらのメカニズムにより、埋め込み先コントロールが埋め込みコントロールで発生するマウスダウンイベントに応答するようにできます。たとえば、ラジオグループコントロールは、埋め込みラジオコントロールに対するクリックをすべて横取りできるため、子の値の設定や再設定をより適切に処理できます。SetControlSupervisor は API ですが、kEventControlInterceptSubviewClick は、埋め込み先コントロール/ビューにインストールする Carbon イベントメッセージにすぎません。Carbon では、後者のメカニズムの使用を強くお勧めします。

先頭に戻る



CountSubControls、GetIndexedSubControl vs. HIViewGetFirstSubview、HIViewGetNextView または HIViewGetLastSubview、HIViewGetPreviousView

これらの API はすべて、サブコントロールまたはサブビューの反復処理に使用できます。